<template>
	<div class="component-upload-image">
		<template v-if="video">
			<div v-for="(item, index) in fileList" :key="index + ''" class="el-upload-list__item">
				<video :src="item.url" width="148" height="148" controls="controls" preload="preload" />
				<div class="el-upload-list__item-actions">
					<el-icon :size="20" color="#FFFFFF" @click="onLookVideo(index)" style="margin-left: 10px">
						<i class="el-icon-zoom-in" />
					</el-icon>
					<el-icon :size="20" color="#FFFFFF" v-if="!isDelete" @click="onRemoveVideo(index)" style="margin-left: 10px">
						<i class="el-icon-delete" />
					</el-icon>
				</div>
			</div>
		</template>
		<draggable v-model="fileList" @update="onDraggableUpdate">
			<transition-group>
				<!-- <el-image v-for="item in fileList" :key="item.uid" :src="item.url" :style="`width:146px;height:146px;`" fit="scale-down" /> -->
				<div v-for="(item, index) in fileList" :key="item.uid" class="el-upload-list__item" style="display: inline-block; margin: 0 8px 8px 0">
					<video v-if="video" :src="item.url" width="150" height="150" controls="controls" preload="preload" />
					<el-image v-else :src="item.url" :style="`width:146px;height:146px;`" fit="scale-down" />
					<div class="el-upload-list__item-actions">
						<el-icon :size="20" color="#FFFFFF" @click="onLookVideo(index)" style="margin-left: 10px">
							<i class="el-icon-zoom-in" />
						</el-icon>
						<el-icon :size="20" color="#FFFFFF" v-if="!isDelete" @click="onRemoveVideo(index)" style="margin-left: 10px">
							<i class="el-icon-delete" />
						</el-icon>
					</div>
				</div>
			</transition-group>
		</draggable>
		<el-upload
			action="#"
			:multiple="Number(maxLength) == 1 ? false : true"
			:accept="video ? 'mp4' : 'image/jpeg,image/jpg,image/png'"
			:on-preview="onPreviewUpload"
			:on-remove="onRemoveUpload"
			:on-error="onErrorUpload"
			:on-change="onChangeUpload"
			:on-exceed="onExceedUpload"
			:before-upload="onBeforeUpload"
			:file-list="fileList"
			list-type="picture-card"
			:http-request="onHttpRequestUpload"
			:limit="maxLength"
			:show-file-list="false"
			:class="{ fileComputed, isDelete, isVideo: fileList.length && video }"
		>
			<i class="el-icon-plus" />
		</el-upload>
		<el-dialog v-if="video" v-model="dialogVisible" title="预览" width="800px" append-to-body>
			<video :src="videoUrl" style="display: block; max-width: 100%; margin: 0 auto" controls="controls" preload="preload" />
		</el-dialog>
		<el-image-viewer v-if="!video && dialogVisible" :initial-index="lookNum" @close="dialogVisible = false" :url-list="fileUrlList" />
	</div>
</template>

<script lang="ts">
import { VueDraggableNext } from 'vue-draggable-next';
import { reactive, toRefs, ref, getCurrentInstance, computed } from 'vue';
import axios from 'axios';
import { ElMessage, ElLoading } from 'element-plus';
import { livesImageUpload } from '/@/api/admin1';
import uploadCos from '/@/utils/uploadCos';
import { randomString } from '/@/utils/utils';

export default {
	name: 'imageUploadCOS',
	components: { draggable: VueDraggableNext },
	props: {
		path: {
			type: String,
			default: 'material',
		},
		modelValue: {
			type: String,
			default: '',
		},
		media_id: {
			type: String,
			default: '',
		},
		maxLength: {
			type: Number,
			default: 1,
		},
		video: {
			type: Boolean,
			default: false,
		},
		disabled: {
			type: Boolean,
			default: false,
		},
		isDelete: {
			type: Boolean,
			default: false,
		},
		isMaterial: {
			type: Boolean,
			default: false,
		},
		isLive: {
			type: Boolean,
			default: false,
		},
	},
	setup(props, { emit }) {
		const state = reactive({
			fileList: [] as any,
			videoUrl: '',
			dialogVisible: false,
			lookValue: '',
			lookNum: 0,
		});

		const uploadLoading = ref(null);
		const { proxy } = getCurrentInstance() as any;

		// 设定一个计算属性 判断是否已经超过上传上限
		const fileComputed = computed(() => {
			return state.fileList.length >= props.maxLength;
		});

		const fileUrlList = computed(() => {
			return state.fileList.map((item: any) => item.url);
		});
		/********** 点击事件(on开头) **********/
		// 视频预览
		const onLookVideo = (num: number) => {
			state.dialogVisible = true;
			state.lookNum = num;
			state.videoUrl = state.fileList[num].url;
		};
		const onDraggableUpdate = () => {
			emit('update:modelValue', state.fileList.map((item: any) => item.url).join(','));
		};
		// 视频删除
		const onRemoveVideo = (num: number) => {
			state.fileList = state.fileList.filter((item: any, index: number) => index !== num);
			emit('update:modelValue', state.fileList.map((item: any) => item.url).join(','));
			props.isLive && emit('update:media_id', '');
		};
		// 图片预览
		const onPreviewUpload = (file: any) => {
			state.dialogVisible = true;
			state.lookNum = state.fileList.findIndex((item: any) => item.url == file.url);
		};
		// 删除图片
		const onRemoveUpload = (file: any) => {
			state.fileList = state.fileList.filter((item: any) => item.uid !== file.uid);
			emit('update:modelValue', state.fileList.map((item: any) => item.url).join(','));
			props.isLive && emit('update:media_id', '');
		};
		// 上传成功
		const onChangeUpload = (file: any, fileList: any) => {
			if (fileList) {
				state.fileList = fileList.map((item: any) => item);
			}
		};
		// 上传失败
		const onErrorUpload = () => {
			(uploadLoading.value as any)?.close();
		};
		// 上传前校验
		const onBeforeUpload = (file: any) => {
			if (props.video) {
				let types = ['video/mp4'];
				const isJPG = types.includes(file.type);
				const isLt2M = file.size / 1024 / 1024 < 5;
				if (!isJPG) {
					ElMessage.warning('只能是 mp4 格式');
					return isJPG;
				}
				if (!isLt2M) {
					ElMessage.warning('上传视频大小不能超过 5M');
					return isLt2M;
				}
			} else {
				let types = ['image/jpeg', 'image/png', 'image/jpg'];
				const isJPG = types.includes(file.type);
				const isLt2M = file.size / 1024 / 1024 < 2;
				if (!isJPG) {
					ElMessage.warning('只能是 jpeg,png,jpg 格式');
					return isJPG;
				}
				if (!isLt2M) {
					ElMessage.warning('上传图片大小不能超过 2MB');
					return isLt2M;
				}
			}
			(uploadLoading.value as any) = ElLoading.service({
				lock: true,
				text: '上传中',
				background: 'rgba(0, 0, 0, 0.7)',
			});
			return true;
		};

		// 自定义上传
		const onHttpRequestUpload = (res: any) => {
			let fileExtension = res.file.name.substring(res.file.name.lastIndexOf('.') + 1);
			let path = `/hbsk_cloud/${props.path}/${proxy.dayjs().year()}/${proxy.dayjs().month()}/${proxy.dayjs().date()}/${randomString(
				32
			).toLowerCase()}.${fileExtension}`;
			if (props.isMaterial) {
				path = `/hbsk_cloud/material/${res.file.name}`;
			}
			if (props.isLive) {
				axios
					.all([uploadCos(res.file, path), _livesImageUpload(res.file)])
					.then(
						axios.spread((res1: any, res2: any) => {
							// 此时上传还没有完成  此时可以这样做 ： 给所有上传成功的图片 加一个属性 upload: true
							state.fileList = state.fileList.map((item: any) => {
								if (item.uid == res.file.uid) {
									//   upload为true表示 该图片已经成功上传到服务器，地址已经是腾讯云的地址了  就不可以执行保存了
									return { url: res1.url, upload: true, uid: item.uid }; // 将本地的地址换成腾讯云地址
								}
								return item;
							});
							emit('update:modelValue', state.fileList.map((item: any) => item.url).join(','));
							emit('update:media_id', res2.data.info.media_id);
							(uploadLoading.value as any)?.close();
						})
					)
					.catch(
						axios.spread(() => {
							(uploadLoading.value as any)?.close();
						})
					);
			} else {
				uploadCos(res.file, path)
					.then((res1: any) => {
						// 此时上传还没有完成  此时可以这样做 ： 给所有上传成功的图片 加一个属性 upload: true
						state.fileList = state.fileList.map((item: any) => {
							if (item.uid == res.file.uid) {
								//   upload为true表示 该图片已经成功上传到服务器，地址已经是腾讯云的地址了  就不可以执行保存了
								return { url: res1.url, upload: true, uid: item.uid }; // 将本地的地址换成腾讯云地址
							}
							return item;
						});
						emit('update:modelValue', state.fileList.map((item: any) => item.url).join(','));
						props.isLive && emit('update:media_id', '');
						(uploadLoading.value as any)?.close();
					})
					.catch(() => {
						(uploadLoading.value as any)?.close();
					});
			}
		};

		const onExceedUpload = (files: any, uploadFiles: any) => {
			ElMessage.warning(
				`当前限制选择 ${props.maxLength} 张图片，本次选择了 ${files.length} 张图片，共选择了 ${files.length + uploadFiles.length} 张图片`
			);
		};
		// 表单重置
		const reset = () => {
			state.fileList = [];
		};
		// 更新数据
		const dataLoading = () => {
			if (props.modelValue) {
				let fileListArray = props.modelValue.split(',');
				state.fileList = fileListArray.map((item: any, index: number) => {
					return { url: item, uid: index + 1 };
				});
			}
		};

		/********** 网络事件 **********/
		// 直播间相关图片上传到微信
		const _livesImageUpload = (params: object) => {
			return livesImageUpload(params);
		};

		return {
			fileComputed,
			fileUrlList,
			onDraggableUpdate,
			onLookVideo,
			onRemoveVideo,
			onPreviewUpload,
			onRemoveUpload,
			onErrorUpload,
			onChangeUpload,
			onExceedUpload,
			onBeforeUpload,
			onHttpRequestUpload,
			reset,
			dataLoading,
			...toRefs(state),
		};
	},
};
</script>

<style lang="scss" scoped>
.component-upload-image {
	display: flex;
	.el-upload-list__item {
		position: relative;
		width: 148px;
		height: 148px;
		border: 1px solid #c0ccda;
		border-radius: 6px;
		video {
			border-radius: 6px;
		}
		.el-upload-list__item-actions {
			position: absolute;
			width: 100%;
			height: 100%;
			left: 0;
			top: 0;
			cursor: default;
			display: inline-flex;
			justify-content: center;
			align-items: center;
			background-color: rgba(0, 0, 0, 0.5);
			border-radius: 6px;
			transition: opacity 0.3;
			opacity: 0;
		}
		&:hover {
			.el-upload-list__item-actions {
				opacity: 1;
			}
		}
	}
}
</style>
